package service

import (
	"context"
	"github.com/spf13/viper"
	"go-shop-api/internal/dao"
	"go-shop-api/internal/model"
	"go-shop-api/pkg/e"
	"go-shop-api/pkg/funs"
	"go-shop-api/pkg/serializer"
	"go-shop-api/pkg/zydhjwt"
	"go-shop-api/pkg/zydhlog"
)

//用户表

type UserService struct {
	Account    string `form:"account" json:"account" binding:"required,len>=6" _:"comment:登录账号"`
	Password   string `form:"password" json:"password" binding:"required" _:"comment:密码 sha1加密"`
	RePassword string `form:"re_password"  json:"re_password" binding:"required,eqfield=Password" _:"comment:密码 sha1加密"`
	Halt       string `form:"halt" json:"halt" _:"comment:密码盐，混淆密码字符串"`
	Desc       string `form:"desc" json:"desc" _:"comment:描述"`
	Phone      string `form:"phone" json:"phone" binding:"required,checkPhone"  _:"comment:手机号"`
	Email      string `form:"email" json:"email" binding:"required,email"  _:"comment:邮箱"`
	Avatar     string `form:"avatar" json:"avatar" _:"comment:头像/微信头像本地地址"`
	//Username string  			`form:"username" json:"username" _:"type:varchar(100);comment:昵称/微信昵称"`
	Nickname string `form:"nickname" json:"nickname" _:"comment:昵称/微信昵称"`
	Sex      uint   `form:"sex" json:"sex" _:"comment:性别/微信性别 0 未知 1 男 2 女"`
	WxOpenid string `form:"wx_openid" json:"wx_openid" _:"comment:openid微信唯一标识"`
	Level    uint   `form:"level" json:"level" _:"comment:会员等级 0 普通会员"`

	//公众号来源
	SubscribeScene string `form:"subscribe_scene" json:"subscribe_scene" _:"comment:用户来源 ADD_SCENE_SEARCH 公众号搜索，ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移，ADD_SCENE_PROFILE_CARD 名片分享，ADD_SCENE_QR_CODE 扫描二维码，ADD_SCENEPROFILE LINK 图文页内名称点击，ADD_SCENE_PROFILE_ITEM 图文页右上角菜单，ADD_SCENE_PAID 支付后关注，ADD_SCENE_OTHERS 其他"`
	//小程序/公众号 永久二维码
	Ticket string `form:"ticket" json:"ticket" _:"comment:永久二维码ticket"`

	//加密的秘钥
	Key string `form:"key" json:"key" binding:"required,len=16"   _:"comment:加密的秘钥"`

	//登录token 可移动到redis上
	Token string `form:"token" json:"token" _:"comment:token用户唯一标识"`

	// 需要使用自定义校验方法checkDate做参数校验的字段Date
	Date string `form:"date" json:"date" binding:"required,datetime=2006-01-02,checkDate"`
	//其中datetime=2006-01-02是内置的用于校验日期类参数是否满足指定格式要求的tag。 如果传入的date参数不满足2006-01-02这种格式就会提示如下错误：
	//
	//{"msg":{"date":"date的格式必须是2006-01-02"}}
	//针对date字段除了内置的datetime=2006-01-02提供的格式要求外，假设我们还要求该字段的时间必须是一个未来的时间（晚于当前时间），像这样针对某个字段的特殊校验需求就需要我们使用自定义字段校验方法了。
	//首先我们要在需要执行自定义校验的字段后面添加自定义tag，这里使用的是checkDate，注意使用英文分号分隔开。

}

// UserLoginService 用户登录
type UserLoginService struct {
	Account  string `form:"account" json:"account" binding:"required" _:"comment:登录账号"`
	Password string `form:"password" json:"password" binding:"required" _:"comment:密码 sha1加密"`
}

// UserUpdateService 用户更新
type UserUpdateService struct {
	Avatar   string `form:"avatar" json:"avatar" _:"comment:头像/微信头像本地地址"`
	Nickname string `form:"nickname" json:"nickname" _:"comment:昵称/微信昵称"`
}

// UserinfoService 用户信息
type UserinfoService struct {
	//加密的秘钥
	Key string `form:"key" binding:"required,len=16"  _:"comment:加密的秘钥"`
}

// Register 注册  serializer
func (service *UserService) Register(ctx context.Context) *serializer.Response {
	//code := e.Success
	////当key为空或者长度不够，返回错误  //key  对称加密  ,这里可以移动到验证器里
	//if service.Key == "" || len(service.Key) != 16 {
	//	return serializer.NewResponse(e.Error, "秘钥长度不足", "秘钥长度不足", nil)
	//}

	userDao := dao.NewUserDao(ctx)
	//通过 账号/昵称/邮箱 判断用户是否存在
	//不存在
	_, ok, err := userDao.ExistOrNotByAccount(service.Account)
	if err != nil {
		return serializer.NewResponse(e.Error, err.Error(), e.TipsGeneral, nil)
	}
	//存在
	if ok {
		return serializer.NewResponse(e.ErrorExistUser, "", e.TipsErrorExistUser, nil)
	}

	//不存在，创建
	userRegister := &model.User{
		Account:  service.Account,
		Nickname: service.Nickname,
		Email:    service.Email,
		Password: service.Password,
		Phone:    service.Phone,
		Avatar:   viper.GetString("path.default_avatar_path"), //使用默认头像
		//积分 - 加密
		Integral:      funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"), // 用户积分
		UsedIntegral:  funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"), //已使用的积分
		TotalIntegral: funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"), //总积分
		//钱包 - 加密
		Wallet:         funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"),      //钱包金额加密 默认 0
		WalletPassword: funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "123456"), //钱包密码加密 默认123456
		UsedWallet:     funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"),      //已经使用的钱包金额
		TotalWallet:    funs.AesEncoding(funs.CutStrNumByScene(service.Account, 6, 2), "0"),      //总钱包金额
		//Desc: "some desc",
		//积分是否需要加密？ 暂时否
	}

	//密码加密
	password, err := funs.BcryptPwd(service.Password, 12)
	if err != nil {
		zydhlog.Error(err.Error())
		return serializer.NewResponse(e.ErrorFailEncrypt, err.Error(), e.TipsGeneral, nil)
	}

	userRegister.Password = password
	//创建用户
	if err = userDao.UserCreate(userRegister); err != nil {
		zydhlog.Error(err.Error())
		return serializer.NewResponse(e.Error, err.Error(), e.TipsGeneral, nil)
	}
	return serializer.NewResponse(e.Success, e.TipsOk, e.TipsSuccessCreateUser, nil)
}

// Login 登录 serializer
func (service *UserLoginService) Login(ctx context.Context) *serializer.Response {
	var user *model.User
	userDao := dao.NewUserDao(ctx)
	//判断用户是否存在
	user, ok, err := userDao.ExistOrNotByAccount(service.Account)
	if !ok || err != nil {
		zydhlog.Error(err.Error())
		return serializer.NewResponse(e.ErrorExistUserNotFind, err.Error(), e.TipsNotExistUser, nil)
	}
	//存在，检验密码
	if !dao.CheckPassword(user.Password, service.Password) {
		zydhlog.Error(e.TipsErrorPwd)
		return serializer.NewResponse(e.ErrorNotCompare, e.TipsNil, e.TipsErrorPwd, nil)
	}

	//获取登录token，token 签发  一般人，权限为0
	token, err := zydhjwt.GenerateToken(user.ID, service.Account, 0)
	if err != nil {
		zydhlog.Error(err.Error())
		return serializer.NewResponse(e.ErrorAuthToken, err.Error(), e.TipsGeneral, nil)
	}
	//返回token和用户信息
	return serializer.NewResponse(e.Success, e.TipsOk, e.TipsSuccessLogin, serializer.TokenData{
		Token: token,
		User:  serializer.BuildUser(user),
	})
}

// Update 修改 serializer
func (service *UserUpdateService) Update(ctx context.Context, uid uint) *serializer.Response {
	var user *model.User
	var err error
	userDao := dao.NewUserDao(ctx)
	//通过ctx中的用户id查找到用户
	user, err = userDao.GetUserByUid(uid)
	if err != nil {
		return serializer.NewResponse(e.ErrorExistUserNotFind, err.Error(), e.TipsNotExistUser, nil)
	}

	isUpdateUser := false
	//修改昵称nickname
	if service.Nickname != "" {
		user.Nickname = service.Nickname
		isUpdateUser = true
	}
	//修改头像
	if service.Avatar != "" {
		user.Avatar = service.Avatar
		isUpdateUser = true
	}
	if isUpdateUser {
		//更新用户
		if err = userDao.UpdateUserById(uid, user); err != nil {
			zydhlog.Error(err.Error())
			return serializer.NewResponse(e.Error, err.Error(), e.TipsGeneral, nil)
		}
	}
	//返回token和用户信息
	return serializer.NewResponse(e.Success, e.TipsOk, e.TipsSuccessOperate, serializer.BuildUser(user))
}

// Userinfo 登录 serializer
func (service *UserinfoService) Userinfo(ctx context.Context, uid uint) *serializer.Response {
	var user *model.User
	var err error
	userDao := dao.NewUserDao(ctx)
	//通过ctx中的用户id查找到用户
	user, err = userDao.GetUserByUid(uid)
	if err != nil {
		return serializer.NewResponse(e.ErrorExistUserNotFind, err.Error(), e.TipsNotExistUser, nil)
	}
	//返回token和用户信息
	return serializer.NewResponse(e.Success, e.TipsOk, e.TipsSuccessOperate, serializer.BuildUserinfo(user, service.Key))
}
